const express = require('express');
const http = require('http');
const {v4: uuidv4} = require('uuid');
const cors = require('cors');


const app = express();

const port = process.env.port || 8000;

const server = http.createServer(app);

app.use(cors());

// 初始化房间和用户名
let connectedUsers = [];
let rooms = [];

app.get('/',function(req,res){
    res.send('Hello world');
})
app.get('/api/room-exists/:roomId',(req,res)=>{
    const {roomId} = req.params;
    const room = rooms.find((room) => room.id === roomId);
    if(room){
        if (room.connectedUsers.length > 3){
            //房间已满
            return res.send({roomExists:true,full:true});
        }else{
            //房间未满
            return res.send({roomExists:true,full:false});
        }
    }else{
        //房间不存在 返回错误结构
        return res.send({roomExists:false});
    }
})

const io = require('socket.io')(
    server, {
        cors:{
            origin:'*',
            methods:['GET','POST']
        },
    }
);
//监听客户端的链接
io.on('connection',(socket) =>{
    console.log(`用户已实现了socket链接${socket.id}`)
    //监听创建房间请求
    socket.on('create-new-room',(data) =>{
       
        console.log(`主持人进入房间`);
        createNewRoomHandler(data,socket);
    })
    socket.on('join-room',(data) =>{
        joinRoomHandler(data,socket);
    })
    socket.on('disconnect',() =>{
        console.log(`${socket.id}`  + "leave disconnect");
        disconnectHandler(socket)
    })
    socket.on('conn-signal',(data)=>{
        signalingHandler(data,socket)
    })
    //初始化对等连接
    socket.on('conn-init',(data) =>{
        initilizeConnectionHandler(data,socket);
    })
});
// socket.io handler
const createNewRoomHandler = (data,socket) => {
    const {identity} = data;
    console.log('room identity=' + identity);
    const roomId = uuidv4();

    //创建新用户
    const newUser = {
        identity:identity,
        id:uuidv4(),
        roomId:roomId,
        socketId:socket.id,
    };

    //将新用户添加已链接的用户数组
    connectedUsers = [...connectedUsers,newUser];

    //创建会议房间
    const newRoom = {
        id:roomId,
        connectedUsers:connectedUsers,
    };
    //新用户加入会议房间
    socket.join(roomId);
    //房间存储
    rooms = [...rooms,newRoom];

    //向客户端发送告知房间已创建
    socket.emit('room-id',{roomId:roomId})
    //发送更新房间通知
    socket.emit('room-update',{connectedUsers:connectedUsers})
}
//加入房间
const joinRoomHandler = (data,socket) =>{
    const {roomId,identity} = data;
    const newUser = {
        identity,
        roomId,
        id:uuidv4(),
        socketId:socket.id,
    };
    //匹配房间
    const room = rooms.find(room => room.id === roomId);
    room.connectedUsers=[...room.connectedUsers,newUser];
    socket.join(roomId);
    connectedUsers = [...connectedUsers,newUser]

    //告知除自己以外的其他已经链接用户准备webRTC对等连接
    room.connectedUsers.forEach((user) => {
        if(user.socketId !== socket.id){
            const data = {
                connUserSocketId:socket.id,
            };
            io.to(user.socketId).emit('conn-prepare',data);
        }
    });

    io.to(roomId).emit('room-update',{connectedUsers:room.connectedUsers})
}
//离开房间
const disconnectHandler = (socket)=>{
    const user = connectedUsers.find(user => user.socketId=== socket.id)
    if(user){
        console.log(user.roomId);
        const room = rooms.find(room => room.id === user.roomId)
        room.connectedUsers = room.connectedUsers.filter(user => user.socketId !== socket.id);
        socket.leave(user.roomId)
        //当会议房间没有人关闭整个会议室，更新房间
        if(room.connectedUsers.length > 0){
            //用户断开webrtc链接
            console.log(`${socket.id}` + 'leave room');
            io.to(room.id).emit('user-disconnected',{socketId:socket.id})
            io.to(room.id).emit('room-update',{connectedUsers:room.connectedUsers})
        }else{
            rooms = rooms.filter((r) => r.id !== room.id)
        }
        
    }
}
server.listen(port,()=>{
console.log(`服务器正在${port}端口号正在运行`);
});

//交换信令数据
const signalingHandler = (data,socket) =>{
    const {connUserSocketId,signal} = data;
    const signalingData = {
        signal:signal,
        connUserSocketId:socket.id,
    };
    io.to(connUserSocketId).emit('conn-signal',signalingData);
}

//初始化对等连接
const initilizeConnectionHandler = (data,socket) =>{
    const {connUserSocketId} = data;
    const initData = {
        connUserSocketId:socket.id
    }
    io.to(connUserSocketId).emit('conn-init',initData);
}